# coding:utf-8
import traceback, datetime, uuid
from sqlalchemy import and_, or_
import glog, gdb
from role import *
from db_tables import *
from account_mgr import MAX_ACCOUNT_ROLES


# { role_id : role, .. }
data = {}
# { conn_id : role_id, .. }
conn_role_map = {}


def init ():
    #* 读取所有活跃玩家
    pass
    

# 获取玩家列表(内存中)
def get_all_roles ():
    return data.values()


# 取得玩家数据
def get (id):    
    if not id in data:
        p = load_role_by_id(id)
        if p:
            data[id] = p
    try:
        p = data[id]
        return p
    except Exception, e:
        glog.error("role_mgr>get, can not get this id:%s" % id)
        raise e
    

# 从数据库中加载数据
def load_role_by_id (id):
    dbrole = db_get_role(id)
    if not dbrole:
        glog.error("role_mgr>load_role_by_id, no this id:%s" % id)
        return None
    
    role = _dbrole_to_role(dbrole)

    glog.log("role_mgr>load_role_by_id, id:%s" % id)
    return role


# 取得玩家数据
def get_roles_by_account (account):
    roles = load_roles_by_account(account)
    for role in roles:
        data[role.id] = role
    return roles


# 如果一个帐号只有一个角色(登录用接口)
def get_one_role_by_account (account):
    roles = get_roles_by_account(account)
    if len(roles) > 0:
        return roles[0]
    return None


# 从数据库中加载数据(登录用接口)
def load_roles_by_account (account):
    dbroles = db_get_roles_by_account(account)
    roles = []

    if len(dbroles) <= 0:
        glog.debug("role_mgr>load_roles_by_account, no role, account:%s" % account)
        return roles

    for dbrole in dbroles:
        role = Role()   # 创建了个新Role对象
        _dbrole_to_role(dbrole, role)
        roles.append(role)
    return roles


# 创建角色
def create_role (account, role_name, role_race):

    # 检测是否已经满了
    dbroles = db_get_roles_by_account(account)
    if len(dbroles) >= MAX_ACCOUNT_ROLES:
    	glog.error("role_mgr>create_role, role count max account:%s" % account)
    	return False

    # 检测名字是否重复
    dbrole = db_get_role_by_name(role_name)
    if dbrole:
        glog.log("role_mgr>create_role FAILED (exists name, account:%s name:%s)" % (account, role_name))
        return False
    
    # 数据库
    role_id = uuid.uuid1().hex # UUID做角色id
    res = db_create_role(account, role_id, role_name, role_race)
    if not res:
        glog.log("role_mgr>db_create_role FAILED (account:%s name:%s)" % (account, role_name))
        return False

    glog.log("role_mgr>create_role, id:%s" % role_id)
    return True


# 删除角色
def delete_role (role_id):
    res = db_delete_role(role_id)
    if not res:
        glog.error("role_mgr>db_delete_role FAILED (account:%s name:%s)" % (account, role_name))
        return False

    # 删除内存数据
    if role_id in data:
        data.pop(role_id)

    glog.log("role_mgr>delete_role id:%s", role_id)
    return True


# 设置login data
def set_login_data (conn_id, account, role_id):
    p = get(role_id)
    p.set_login_data(conn_id, account)
    conn_role_map[conn_id] = role_id    # 记录 conn_id -> role_id


def get_role_by_conn_id (conn_id):
    if conn_role_map.has_key(conn_id):
        role_id = conn_role_map[conn_id]
        return get(role_id)
    else:
        print "role_mgr>get_role_by_conn_id: no this id:", conn_id
        return None


# 转化dbrole到Role
def _dbrole_to_role(dbrole, role):
    role.id = dbrole.id
    role.account = dbrole.account
    role.name = dbrole.name
    role.race = dbrole.race


# ------------------------------------------------------
def db_create_role (account, role_id, role_name, role_race):
    ses = gdb.get_session()
    create_time = datetime.datetime.now()

    try:
        ses.add(DBRole(role_id, account, role_name, role_race, create_time))
        ses.commit()
        return True
    except Exception, e:
        ses.rollback()
        return False


# 这接口是真的删除掉角色了
# 一般做法是需要将角色移动到一个备份的数据库中, 当要恢复的时候可以恢复, 当然还包括其他的数据
def db_delete_role (role_id):
    ses = gdb.get_session()

    dbrole = db_get_role(role_id)
    if dbrole is None:
        glog.error("role_mgr>db_delete_role FAILED (no this id:%s)", role_id)
        return False

    ses.delete(dbrole)
    ses.commit()
    return True
    

def db_get_role_by_name (name):
    ses = gdb.get_session()
    return ses.query(DBRole).filter_by(name=name).first()


def db_get_role (id):
    ses = gdb.get_session()
    return ses.query(DBRole).filter_by(id=id).first()


def db_get_roles_by_account (account):
    ses = gdb.get_session()
    return ses.query(DBRole).filter_by(account=account).all()

